﻿FilterClassesRegex = /^(invisi|group)$/;

String.prototype.filterClasses = function (filter) {
    var ar = jQuery.trim(this).replace(/\s+/g, ' ').split(' '), ot = '', rx = filter || FilterClassesRegex;
    for (var i = 0; i < ar.length; i++) {
        if (!ar[i] || rx.test(ar[i])) continue;
        ot += '.' + ar[i];
    }
    return ot;
};


jQuery.fn.extend({

    actualElement: function () {
        var $pp = this, tag;
        // If click is inside an 'a' or button, then move up to the level of the 'a' or button
        while ($pp && $pp.length > 0) {
            tag = $pp[0].tagName;
            if (!tag) break;
            if (/^(a|button)$/i.test(tag)) return $pp;
            $pp = $pp.parent();
        }
        // For Safari must drill down to embed tag inside an object tag
        if (this.is('object') && this.children('embed').length > 0)
            return this.children('embed').first();
        return this;
    },

    selecTo: function (options) {
        options = options || {};
        var ar = [], $p = jQFrames(this, options.bind).actualElement(), ot = '', tag, id, cls, $sel, idx, typ, txt, hrf;
        // Construct the chain
        while ($p && $p.length > 0) {
            tag = $p[0].tagName.toLowerCase();
            id = $p.attr('id');
            cls = ($p.attr('class') || '').filterClasses(options.classFilter);
            typ = tag == 'input' ? $p.attr('type') : '';
            txt = !ar.length && $p.is('a,h1,h2,h3,h4,span,p,th,td') ? jQuery.trim($p.text()) : '';
            hrf = $p.is('a') ? jQuery.trim($p.attr('href')) : '';
            if (/^javascript:/i.test(hrf)) hrf = '';
            idx = null;
            if (id)
                ot += '#' + id;
            else {
                ot += tag;
                if (typ) ot += '[type=' + typ + ']';
            }
            if (hrf && options.href) ot += '[href="' + hrf + '"]';
            if (cls) ot += cls;
            if (txt && options.text) ot += ':hastext(' + txt.replace(/"/g, '\\"') + ')';
            $sel = $p.parent().children(ot);
            if ($sel.length > 1) $sel.each(function (i) {
                if (this === $p[0]) {
                    idx = i;
                    return false;
                }
                return true;
            });
            if (idx !== null) ot += ':eq(' + idx + ')';
            ar.push(ot);
            ot = '';
            if (tag == 'body') break;
            $p = $p.parent();
            // If we have found an id and the id is unique stop here
            if (id && jQFrames(tag + '[id=' + id + ']').length == 1) break;
            // Stop at the tree top or the body tag
            if (!$p.length || !$p[0].tagName || $p[0].tagName.toLowerCase() == 'body') break;
        }
        if (ar.length && ar[ar.length - 1].substr(0, 1) != '#' && !$p.is('body')) ar.push('body');
        ar.reverse();
        // Turn the chain into a string bound with ">"
        var pStop = options.parent ? ar.length - 1 : ar.length;
        for (var i = 0; i < pStop; i++) {
            if (ot) ot += '>';
            ot += ar[i];
        }
        return ot;
    },

    idPath: function () {
        var $p = this, ot = '';
        while ($p.length && !$p[0].id) {
            $p = $p.parent();
            ot += '>';
        }
        if ($p.length && $p[0].id) return '#' + $p[0].id + (ot || ':');
        return '';
    },

    identifier: function (options) {
        var $p = jQFrames(this, (options || {}).bind).actualElement(), ot = '';
        if ($p.length) {
            var id = $p.idPath(), v = ($p.Val() || '').trim(), placeholder = $p.attr('placeholder');
            if (id) ot += id;
            ot += $p[0].tagName.toUpperCase();
            if ($p.is('img')) ot += '[' + $p[0].src.pathEnd() + ']';
            if (v || placeholder) ot += '[' + (v.partial(18) || placeholder.partial(18)) + ']';
        }
        return ot;
    }

});

function jQFrames(sel, ctx) {
    return jQuery(sel, ctx);
};
